import glob
import os

import psycopg2
from psycopg2 import OperationalError

"""
【openGauss︱PostgreSQL】openGauss或PostgreSQL根据文件名升序排序，批量执行文件夹下的sql脚本，文件报错回滚
"""


class ExecuteSQLScriptsFromFolder:
    def __init__(self, dbname, user, password, host='localhost', port=5432):
        """
        初始化数据库连接参数
        :param dbname: 数据库名称
        :param user: 用户名
        :param password: 密码
        :param host: 主机地址（默认localhost）
        :param port: 端口号（默认5432）
        """
        self.conn_params = {
            'dbname': dbname,
            'user': user,
            'password': password,
            'host': host,
            'port': port
        }
        self.connection = None

    def connect(self):
        """建立数据库连接"""
        try:
            self.connection = psycopg2.connect(**self.conn_params)
            print("成功连接到PostgreSQL数据库")
            return True
        except OperationalError as e:
            print(f"连接错误: {e}")
            return False

    def disconnect(self):
        """关闭数据库连接"""
        if self.connection:
            self.connection.close()
            print("数据库连接已关闭")

    def execute_procedure_script(self, script_path):
        """
        执行存储过程创建脚本
        :param script_path: SQL脚本文件路径
        :return: 执行是否成功
        """
        if not self.connection:
            print("未建立数据库连接")
            return False

        try:
            # 读取SQL脚本文件内容
            with open(script_path, 'r', encoding='utf-8') as file:
                sql_script = file.read()

            # 使用事务执行脚本
            with self.connection.cursor() as cursor:
                cursor.execute(sql_script)
            self.connection.commit()
            print("存储过程创建成功")
            return True

        except Exception as e:
            self.connection.rollback()
            print(f"执行错误: {e}")
            return False


def print_sql_files_sorted(folder_path, manager: ExecuteSQLScriptsFromFolder):
    """
    读取指定文件夹下所有.sql文件，按文件名升序排序后打印内容

    参数:
        folder_path (str): 要扫描的文件夹路径
    """
    # 检查文件夹是否存在
    if not os.path.exists(folder_path):
        print(f"错误：文件夹 '{folder_path}' 不存在")
        return

    # 获取所有.sql文件的完整路径，并按文件名升序排序
    sql_files = sorted(glob.glob(os.path.join(folder_path, "*.sql")))

    # 如果没有找到SQL文件
    if not sql_files:
        print(f"在 '{folder_path}' 中未找到.sql文件")
        return

    result = False

    # 逐个读取并打印文件内容
    for file_path in sql_files:
        file_name = os.path.basename(file_path)
        print(f"\n{'=' * 50}")
        print(f"文件: {file_name}")
        print(f"文件完整路径: {file_path}")
        print(f"{'=' * 50}")

        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                content = file.read()
                print(content)

                if manager.connect():
                    # 执行存储过程创建脚本
                    result = manager.execute_procedure_script(file_path)
                    manager.disconnect()
                if result:
                    print("执行脚本成功！")
                else:
                    break
        except UnicodeDecodeError:
            try:
                # 尝试使用其他编码
                with open(file_path, 'r', encoding='latin-1') as file:
                    content = file.read()
                    print(content)

                    if manager.connect():
                        # 执行存储过程创建脚本
                        result = manager.execute_procedure_script(file_path)
                        manager.disconnect()
                    if result:
                        print("执行脚本成功！")
                    else:
                        break
            except Exception as e:
                print(f"读取文件 '{file_name}' 时出错: {str(e)}")
        except Exception as e:
            print(f"读取文件 '{file_name}' 时出错: {str(e)}")
            print("执行脚本失败！")
            break


# 使用示例
if __name__ == "__main__":
    # 数据库配置
    manager = ExecuteSQLScriptsFromFolder(
        dbname="tzq_dev_db",
        user="tzq",
        password="Tzq@123456",
        host="7.203.228.46",
        port=8000
    )

    # SQL脚本文件目录
    sql_dir = r"D:\test\2025-07-19\tzq"

    # 根据文件名升序执行目录下的SQL脚本，哪个文件报错，那个文件执行的内容会回滚，同时程序停止运行
    print_sql_files_sorted(sql_dir, manager)
